Azure VM’s uitrollen met Terraform

Het is alweer te lang geleden dat ik iets gepost heb. In die tijd regelmatig bezig geweest met het uitrollen van VM’s met behulp van Terraform. Dit o.a. op hypervisors als VMWare en Proxmox. Aangezien er een steeds verdere migratie bezig is van On-Premise naar cloud, ben ik ook maar in de magische wereld van Azure gedoken.
De volgende stap is dus het uitrollen van VM’s in Azure.

Waar je bij de on-prem omgevingen meestal gewoon een resource aanmaakt met disk, netwerk en compute zijn dat bij Azure allemaal losse resources. Om een uitrol te doen moet je dus het volgende plaatje in de gaten houden.

Kortom, de resources die we nodig hebben zijn:

  • Virtueel netwerk
  • Subnet
  • Netwerk interface
  • Publiek IP adres
  • De virtuele machine zelf, met daarin een os disk. Deze wordt aangemaakt bij het aanmaken van de VM.

Verder hebben we ook een image nodig, welke niet een aparte resource is en natuurlijk de terraform azurerm provider. Om gebruik te kunnen maken van de Azure omgeving moeten we in Azure een subscription hebben en een resource group. Eventueel kun je de resource group ook met behulp van Terraform maken, mara in dit voorbeeld is die er al. Om 1 en ander wat flexibeler te maken gebruik ik altijd een var.tf file om wat variabelen te definiƫren.

De inhoud van deze var.tf file is als volgt:

variable "subscription_id" {
default = "4xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
description = "Azure Subscription ID"
}

variable "resourcegroupname" {
default = "myresourcegroup"
description = "Location"
}

variable "location" {
default = "South Central US"
description = "Location"
}

variable "vmsize" {
default = "standard_d2s_v3"
description = "Size of vm"
}

variable "offer" {
default = "0001-com-ubuntu-server-focal"
description = "Offer For Ubuntu =< 18.04 default should be UbuntuServer"
}

variable "sku" {
default = "20_04-lts"
description = "SKU"
}

variable "admin_username" {
default = "ubuntu"
description = "Username"
}

variable "admin_password" {
default = "Super-Secret2022"
description = "Password"
}

variable "hostname" {
default = "ubuntu-svr1"
description = "Hostname"
}

De variabelen kun je naar wens aanpassen.
Vervolgens hebben we ook nog een main.tf. De inhoud daarvan is als volgt:


#
# first run: az login
#

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "3.32.0"
    }
  }
}

provider "azurerm" {
  features {}
  skip_provider_registration = true
  subscription_id = var.subscription_id
}

## Create a resource group
#resource "azurerm_resource_group" "example" {
#  name     = var.resourcegroupname
#  location = var.location
#}

# Create a virtual network within the resource group
variable "prefix" {
  default = "myazurespace"
}

data "azurerm_resource_group" "example" {
  name     = var.resourcegroupname
}

resource "azurerm_virtual_network" "main" {
  name                = "${var.prefix}-network1"
  address_space       = ["10.0.0.0/16"]
  location            = data.azurerm_resource_group.example.location
  resource_group_name = data.azurerm_resource_group.example.name
}

resource "azurerm_subnet" "internal" {
  name                 = "internal"
  resource_group_name  = data.azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.2.0/24"]
}

resource "azurerm_network_interface" "main" {
  name                = "${var.prefix}-nic1"
  location            = data.azurerm_resource_group.example.location
  resource_group_name = data.azurerm_resource_group.example.name

  ip_configuration {
    name                          = "testconfiguration1"
    subnet_id                     = azurerm_subnet.internal.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.example.id
  }
}
resource "azurerm_public_ip" "example" {
  name                = "${var.prefix}-pip1"
  resource_group_name = data.azurerm_resource_group.example.name
  location            = data.azurerm_resource_group.example.location
  allocation_method   = "Static"

  tags = {
    environment = "Production"
  }
}

resource "azurerm_virtual_machine" "main" {
  name                  = "${var.prefix}-vm1"
  location              = data.azurerm_resource_group.example.location
  resource_group_name   = data.azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.main.id]
  vm_size               = var.vmsize

  # Uncomment this line to delete the OS disk automatically when deleting the VM
  delete_os_disk_on_termination = true

  # Uncomment this line to delete the data disks automatically when deleting the VM
  delete_data_disks_on_termination = true

  storage_image_reference {
    publisher = "Canonical"
    offer     = var.offer
    sku       = var.sku
    version   = "latest"
  }
  storage_os_disk {
    name              = "${var.prefix}-osdisk1"
    caching           = "ReadWrite"
    create_option     = "fromimage"
    managed_disk_type = "Standard_LRS"
  }
  os_profile {
    computer_name  = var.hostname
    admin_username = var.admin_username
    admin_password = var.admin_password
  }
  os_profile_linux_config {
    disable_password_authentication = false
  }
  tags = {
    environment = "staging"
  }
}

output "Public_IP_address" {
  value = "${azurerm_public_ip.example.*.ip_address}"
}
output "Username" {
  value = var.admin_username
}
output "Password" {
  value = var.admin_password
}

Ook hier kun je de nodige aanpassingen maken of eventueel variabelen gebruiken welke je hebt toegevoegd in het var.tf bestand.

Om dit hele spul nu uit te kunnen voeren installeren we eerst de azure omgeving op je Linux systeem. Hoe dat moet vind je op de website van Micro$oft:
https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt

Vervolgen typen we op de console:

az login

En volgen de instructies op je scherm.
Als je ingelogd bent kunnen we vervolgens de volgende terraform stappen doen:

terraform init
terraform plan
terraform apply

Als alles goed gegaan is, is er nu een VM uitgerold en vind je op de console van je Linux systeem het ipadres, de inlognaam en het wachtwoord waarmee je kunt inloggen.
Let er op dat dit dus niet super veilig is. Beter is het om in te loggen met bijv. een certificaat, firewall regels in te stellen e.d.
Dit gaan we misschien in een volgende post bekijken.